/*
 *    sw1_interrupt.c  -  interrupt api & driver
 *
 *	  Board:		akae2440
 *    environment:	bootloader & ADS
 *    Author:		akaedu
 *    Date:			2009-5-26
 *    web:			www.akaedu.org
 *
 *  
 *	  GPIO address_MAP
 *	  
 *	  CPLD_MAP_BASE	physical address is	0x20800000		
 *	  CPLD_LED		physical address is	0x20800000		
 *	  CPLD_SEG		physical address is	0x20800080
 *	  CPLD_DIP		physical address is	0x208000a0
 *
 *	  GPIO port_MAP   
 *	  
 *	  GPA_PORT~GPB_PORT(130 multi-functional input port pins)
 *	  GPIO_BASE	:	GPACON	:	0x56000000	
 *	  
 *	  NAME			GPIO		CPLD_IN		CPLD_OUT	GPIO_CON		MODE_bit_CON	GPIO_DAT		MODE_bit_DAT		
 *	  BEEP			GPB0		TOUT0		BEEP		0x56000010		[1:0]			0x56000014		[0]
 *
 *	  GPIO key_scn_MAP
 *
 *	  NAME			PORT_OUT			PORT_IN			
 *	  KEY(sw1)		KBOUT1 : GPB8		KBIN1 : ENT0 : GPF0				
 *	  KEY(sw2)		KBOUT0 : GPB9		KBIN1 : ENT0 : GPF0			
 *	  KEY(sw3)		KBOUT1 : GPB8		KBIN0 : ENT2 : GPF2				
 *	  KEY(sw4)		KBOUT1 : GPB8		KBIN1 : ENT2 : GPF2				
 *
 *	  GPIO_CON						GPIO_DAT				GPIO		MODE_bit_CON		MODE_bit_DAT
 *	  GPBCON : 0x56000010			GPBDAT : 0x56000014		GPB8		[17:16]				[8]			
 *	  GPBCON : 0x56000010			GPBDAT : 0x56000014		GPB9		[19:18]				[9]			
 *	  GPFCON : 0x56000050			GPBDAT : 0x56000054		GPF0		[1:0]				[0]			
 *	  GPFCON : 0x56000050			GPBDAT : 0x56000054		GPF2		[5:4]				[2]			
 *
 */
#include "beep.h"
#include "led.h"
#include "key.h"


#define  GPBCON		(*((volatile unsigned int *)0x56000010))        
#define  GPBDAT		(*((volatile unsigned int *)0x56000014)) 
#define  GPFCON		(*((volatile unsigned int *)0x56000050))        
#define  GPFDAT		(*((volatile unsigned int *)0x56000054)) 
/* touch off interrupt mode */
#define  EXTINT0	(*((volatile unsigned int *)0x56000088))

#define SRCPND		(*((volatile unsigned int *)0x4a000000))
#define INTMOD		(*((volatile unsigned int *)0x4a000004))
#define INTMSK		(*((volatile unsigned int *)0x4a000008))
#define PRIORITY	(*((volatile unsigned int *)0x4a00000c))
#define INTPND		(*((volatile unsigned int *)0x4a000010))
#define INTOFFSET	(*((volatile unsigned int *)0x4a000014))
#define SUBSRCPND	(*((volatile unsigned int *)0x4a000018))
#define SUBINTMSK	(*((volatile unsigned int *)0x4a00001c))

/* falling edge triggered [2:0] : 01x */
#define INT0_IO_FALLING_EDGE		(2)
#define INT0_IO_LOW_LEVEL		(0)



/* delay for about one second */
static void delay(int time)	
{
	int i, j;

	for(i = 0; i < time; i++)
		for(j = 0; j < 7000000; j++)
			;
}

void do_irq( void )
{ 
	led_on(7);
	delay(1);
	led_off(7);
		
}

void install_irq_handler( void (*isr)(void) )
{
	/* ARM irq exception vector addr is 0x00000018  */
	unsigned int * irq_vec_addr = ( unsigned int * ) 0x18;
	/* this is isr entry address, could be another address like 0x3c, 0x58... */
	unsigned int * isr_entry_addr = ( unsigned int * ) 0x38;

	unsigned int instruction;
	
	/* set the ISR entry at 0x38  */
	*isr_entry_addr = (unsigned int)isr;
	
	/* make an instruction: it is machine-code for "ldr  pc, [pc, #(38-18-8)]"  */
	instruction = ((unsigned int) isr_entry_addr  - (unsigned int)irq_vec_addr - 0x08) | 0xe59ff000;
	
	/* set this instruction at 0x18  */
	*irq_vec_addr = instruction;	
	
	return;
}


void irq_init(void);

void irq_handler(void);

int main(void)
{
	int i = 0;
	

	install_irq_handler( irq_handler );
	
	led_init();
	key_init();
	
	/* KBOUT1 : SW1 can trigger */
	GPBDAT &= ~(1<<8);
	GPBDAT |= 1<<9;

	
	while(++i)
	{
		led_on(i%7);
		delay(1);
		led_off(i%7);
		delay(1);
	}

	return 0;
}

void __rt_entry(void)
{
	main();	
}
 
